home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_ImportAdv / epsfwriter.m < prev    next >
Text File  |  1992-12-19  |  10KB  |  442 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    epsfwriter.c
  35.  *
  36.  *    Version:    2.0
  37.  *    Author:    Ken Fromm
  38.  *    History:
  39.  *            03-07-91        Added this comment.
  40.  */
  41.  
  42. #import <appkit/NXBitmapImageRep.h>
  43. #import <appkit/color.h>
  44. #import <appkit/graphics.h>
  45. #import <appkit/nextstd.h>
  46. #import <appkit/tiff.h>
  47.  
  48. #import <dpsclient/dpsclient.h>
  49. #import <dpsclient/wraps.h>
  50. #import <objc/List.h>
  51. #import <objc/hashtable.h>
  52. #import <streams/streamsimpl.h>
  53. #import <streams/streams.h>
  54.  
  55. #import "ImportApp.h"
  56. #import "epsfstruct.h"
  57. #import "epsfwraps.h"
  58.  
  59. #define MAX_CHARS       255
  60. #define MAX_BYTES       127
  61.  
  62. extern void        GetDocumentComment();
  63. extern NXColor    GetColorAt(NXBitmapImageRep *image, int x, int y);
  64. extern void        LogEpsfError();
  65.  
  66. /*
  67. *    These arrays contain the proper instructions for including, initiating
  68. *    and terminating procedure sets using the Adobe Illustrator format.
  69. */
  70. const static char EpsfProcSetDef[ ] =
  71. "% EPSF_Illustrator_abbrev
  72. % Version 1.0 8/23/1990
  73. % Copyright (C) 1987, 1988, 1989, 1990
  74. % Adobe Systems Incorporated
  75. % All Rights Reserved
  76.  
  77. userdict /EPSF_Illustrator_abbrev  14  dict dup begin put
  78. % initialization
  79. /initialize                % - initialize -
  80. {
  81. userdict /EPSF_Illustrator_abbrev_vars 1 dict dup begin put
  82. /_i null def
  83. EPSF_Illustrator_abbrev begin
  84. EPSF_Illustrator_abbrev
  85.     {
  86.     dup xcheck
  87.         {
  88.         bind
  89.         } if
  90.     pop pop
  91.     } forall
  92. end
  93. end
  94. EPSF_Illustrator_abbrev begin
  95. EPSF_Illustrator_abbrev_vars begin
  96. newpath
  97. } def
  98.  
  99. /terminate                % - terminate -
  100. {
  101. end
  102. end
  103. } def
  104.  
  105. /ddef                % key value ddef -
  106. {
  107. EPSF_Illustrator_abbrev_vars 3 1 roll put
  108. } def
  109.  
  110. /npop                % integer npop -
  111. {
  112.     {
  113.     pop
  114.     } repeat
  115. } def
  116.  
  117. % color operators
  118. /g                    % gray g -
  119. {
  120. setgray
  121. } def
  122.  
  123. % graphic state operators
  124. /d                    % array phase d -
  125. {
  126. setdash
  127. } def
  128. /cf                    % - cf flatness
  129. currentflat def
  130. /i                    % flatness i -
  131. {
  132. dup 0 eq
  133.     {
  134.     pop cf
  135.     } if
  136. setflat
  137. } def
  138. /j                    % linejoin j -
  139. {
  140. setlinejoin
  141. } def
  142. /J                    % linecap J -
  143. {
  144. setlinecap
  145. } def
  146. /M                    % miterlimit M -
  147. {
  148. setmiterlimit
  149. } def
  150. /w                    % linewidth w -
  151. {
  152. setlinewidth
  153. } def
  154.  
  155. % place operators
  156. /`                    % matrix llx lly urx ury string ` -
  157. {
  158. /_i save ddef
  159. pop 5 -1 roll concat
  160. newpath 4 2 roll  2 copy moveto
  161. 3 1 roll 1 index lineto
  162. 2 index exch lineto
  163. lineto
  164. closepath
  165. clip newpath
  166. userdict begin
  167. /showpage {} def
  168. } def
  169.  
  170. /~                    % - ~ -
  171. {
  172. end
  173. _i restore
  174. } def
  175.  
  176. currentdict readonly pop end\n";
  177.  
  178. const static char EpsfProcSetInit[ ] = "EPSF_Illustrator_abbrev /initialize get exec\n";
  179.  
  180. const static char EpsfProcSetTerm[ ] = "EPSF_Illustrator_abbrev /terminate get exec\n";
  181.  
  182. void  WriteEpsfProcSetDef ()
  183. {
  184.     DPSWritePostScript(DPSGetCurrentContext(), EpsfProcSetDef, strlen(EpsfProcSetDef));
  185. }
  186.  
  187. void  WriteEpsfProcSetInit ()
  188. {
  189.     DPSWritePostScript(DPSGetCurrentContext(), EpsfProcSetInit, strlen(EpsfProcSetInit));
  190. }
  191.  
  192. void  WriteEpsfProcSetTerm ()
  193. {
  194.     DPSWritePostScript(DPSGetCurrentContext(), EpsfProcSetTerm, strlen(EpsfProcSetTerm));
  195. }
  196.  
  197. /*
  198. *    Writes the Adobe Illustrator 88 imported document operator.
  199. */
  200. void  WriteEpsfIllustratorBeg(NXRect  *bounds, NXRect *boundsOrig, float rotation, char *filename)
  201. {
  202.     float            a = 1.0, b = 0.0, 
  203.                 c = 0.0, d = 1.0,
  204.                 sx = 1.0, sy = 1.0;
  205.  
  206.     NXPoint        t;
  207.  
  208.     DPSContext    ctxt;
  209.  
  210.     if (boundsOrig->size.width)
  211.         sx = bounds->size.width/boundsOrig->size.width;
  212.     if (boundsOrig->size.height)
  213.         sy = bounds->size.height/boundsOrig->size.height;
  214.  
  215.     if (rotation != 0.0)
  216.     {
  217.         a = d = (float) cos(rotation);
  218.         b = c = (float) sin(rotation);
  219.         c = -c;
  220.     }
  221.     a = a * sx;
  222.     b = b * sx;
  223.     c = c * sy;
  224.     d = d * sy;
  225.  
  226.     t.x = bounds->origin.x - boundsOrig->origin.x * sx;
  227.     t.y = bounds->origin.y - boundsOrig->origin.y * sy;
  228.     
  229.     ctxt = DPSGetCurrentContext();
  230.     DPSPrintf(ctxt, "\n0 g 0 i 0 J 0 j 1 w 10 M [] 0 d\n");
  231.     DPSPrintf(ctxt, "[%g %g %g %g %g %g] %g %g %g %g", a, b, c, d, t.x, t.y,
  232.         boundsOrig->origin.x, boundsOrig->origin.y,
  233.         boundsOrig->origin.x + boundsOrig->size.width,
  234.         boundsOrig->origin.y + boundsOrig->size.height);
  235.     if (filename)
  236.         DPSPrintf(ctxt, " (%s)", filename);
  237.     else
  238.         DPSPrintf(ctxt, " ( )");
  239.     DPSPrintf(ctxt, " `\n");
  240.  
  241.     DPSPrintf(ctxt, "%%%%BeginDocument: ");
  242.     if (filename)
  243.         DPSPrintf(ctxt, "%s", filename);
  244.     DPSPrintf(ctxt,"\n");
  245. }
  246.  
  247. void  WriteEpsfIllustratorInclude(char *name)
  248. {
  249.     DPSContext    ctxt;
  250.  
  251.     ctxt = DPSGetCurrentContext();
  252.     DPSPrintf(ctxt, "%%%%IncludeFile: ");
  253.     if (name)
  254.         DPSPrintf(ctxt, "%s", name);
  255.     DPSPrintf(ctxt, "\n");
  256. }
  257.  
  258. void  WriteEpsfIllustratorEnd()
  259. {
  260.     DPSContext    ctxt;
  261.  
  262.     ctxt = DPSGetCurrentContext();
  263.     DPSPrintf(ctxt, "%%%%EndDocument\n");
  264.     DPSPrintf(ctxt, "~\n\n");
  265. }
  266.  
  267. void  WriteEpsfResource(id list, int i, int j)
  268. {
  269.     int            k, count,
  270.                 linelen, datalen, commentlen;
  271.  
  272.     char            comment[EPSF_MAXCOMMENTSUB];
  273.  
  274.     NXAtom        data;
  275.  
  276.     DPSContext    ctxt;
  277.  
  278.     count = [list  count];
  279.     if (count)
  280.     {
  281.         ctxt = DPSGetCurrentContext();
  282.         GetDocumentComment(comment, i, j);
  283.         DPSPrintf(ctxt, comment);
  284.  
  285.         linelen = commentlen = strlen(comment);
  286.         for (k = 0; k < count; k++)
  287.         {
  288.             data = (NXAtom) [list  objectAt:k];
  289.             datalen = strlen(data);
  290.             if (datalen + linelen > EPSF_MAXCOMMENT)
  291.             {
  292.                 /* Prevents an infinite loop for a single large datalen. */
  293.                 if (commentlen != linelen)
  294.                 {
  295.                     DPSPrintf(ctxt, "\n%%%%+");
  296.                     linelen = commentlen = 3;
  297.                 }
  298.             }
  299.  
  300.             DPSPrintf(ctxt, " %s", data);
  301.             linelen += datalen;
  302.         }
  303.  
  304.         DPSPrintf(ctxt, "\n");
  305.     }
  306. }
  307.  
  308. static char GetBlackWhiteAt(NXBitmapImageRep *image, int x, int y)
  309. {
  310.     int             bps, spp, amask;
  311.  
  312.     unsigned char        gray;
  313.  
  314.     spp = [image samplesPerPixel];
  315.     bps = [image bitsPerSample];
  316.  
  317.     amask = (1 << bps) - 1;    // 1, 3, 15, 255 for bps = 1, 2, 4, 8
  318.     if ([image isPlanar])
  319.     {
  320.         int pixel = x * bps;
  321.         int byteLoc = [image bytesPerRow] * y + (pixel >> 3);
  322.         int bitLoc = pixel & 7;
  323.             gray = ((*([image  data]+byteLoc)) >> (8 - bitLoc - bps)) & amask;
  324.     }
  325.     else
  326.     {
  327.         unsigned char *byteLoc = [image  data] + [image bytesPerRow] * y;
  328.         int bitLoc = x * bps * spp;
  329.         gray = ((byteLoc[bitLoc >> 3]) >> (8 - (bitLoc & 7) - bps)) & amask;
  330.     }
  331.  
  332.     return (gray >> 1 ? 0 : 1);
  333. }
  334.  
  335. void WriteEpsfPreview(id  image)
  336. {
  337.     int            byte, orbyte;
  338.  
  339.     int            i, j, width, height,
  340.                 pos, bytes;
  341.  
  342.     DPSContext    ctxt;
  343.  
  344.     if (image)
  345.     {
  346.         ctxt = DPSGetCurrentContext();
  347.  
  348.         width = [image  pixelsWide];
  349.         height = [image  pixelsHigh];
  350.         DPSPrintf(ctxt, "%%%%BeginPreview: %d %d %d %d",
  351.                 width, height, 1, (((width-1)/8)/MAX_BYTES + 1) *height);
  352.         for (i = 0; i < height; i++)
  353.         {
  354.             DPSPrintf(ctxt, "\n%% ");
  355.             pos = 7;
  356.             byte = 0;
  357.             bytes = 0;
  358.             for (j = 0; j < width; j++, pos--)
  359.             {
  360.                 orbyte = GetBlackWhiteAt(image, j, i) << pos;
  361.                 byte = byte | orbyte;
  362.                 if (pos == 0 || j == width - 1)
  363.                 {
  364.                     bytes++;
  365.                     if (bytes > MAX_BYTES)
  366.                     {
  367.                         bytes = 0;
  368.                         DPSPrintf(ctxt, "\n%% ");
  369.                     }
  370.                     DPSPrintf(ctxt, "%02x", byte);
  371.                     pos = 8;
  372.                     byte = 0;
  373.                 }
  374.             }
  375.         }
  376.         DPSPrintf(ctxt, "\n%%%%EndPreview\n\n");
  377.     }
  378. }
  379.  
  380. /*
  381. *    This does nothing in the way of error recovery. It is used to demonstrate the
  382. *    problems on not using a separate context. Eps files with errors can potentially
  383. *    harm the application's context. The recommended approach is to use
  384. *    the NXEPSImageRep object to image the file.
  385. */
  386. int  WriteEpsf(const char *name, NXRect *bounds, NXRect *boundsOrig)
  387. {
  388.     BOOL        trace;
  389.  
  390.     int            error, len, maxlen;
  391.  
  392.     char            *data;
  393.  
  394.     NXStream    *stream;
  395.  
  396.     DPSContext    ctxt;
  397.  
  398.     trace = [NXApp  tracingFlag];
  399.     error = EPSF_OK;
  400.     stream = NXMapFile(name, NX_READONLY);
  401.     if (stream)
  402.     {
  403.         NXGetMemoryBuffer(stream, &data, &len, &maxlen);
  404.         if (data && len)
  405.         {
  406.             ctxt = DPSGetCurrentContext();
  407.             error = EPSF_WRITEERROR;
  408.             NX_DURING
  409.                 DPSTraceContext(ctxt, trace);
  410.  
  411.                 PSWBeginEpsf();
  412.                 PSWSetEpsf(bounds->origin.x, bounds->origin.y, bounds->size.width,
  413.                     bounds->size.height, boundsOrig->origin.x, boundsOrig->origin.y,
  414.                     boundsOrig->size.width, boundsOrig->size.height, 0);
  415.  
  416.                 DPSPrintf(ctxt, "%%%%BeginDocument: %s\n", name);
  417.                 DPSPrintf(ctxt, "%%%% ...Included EPS file here... \n");
  418.  
  419.                 DPSTraceContext(ctxt, NO);
  420.                 DPSWritePostScript(ctxt, data, len);
  421.                 DPSTraceContext(ctxt, trace);
  422.  
  423.                 DPSPrintf(ctxt, "%%%%EndDocument\n");
  424.  
  425.                 PSWEndEpsf();
  426.                 DPSTraceContext(ctxt, NO);
  427.  
  428.                 DPSFlushContext(ctxt);
  429.  
  430.                 error = EPSF_OK;
  431.             NX_HANDLER
  432.                 if (NXLocalHandler.code == dps_err_ps)
  433.                     LogEpsfError(&NXLocalHandler);
  434.                 else
  435.                     NX_RERAISE();
  436.             NX_ENDHANDLER
  437.         }
  438.     }
  439.  
  440.     return error;
  441. }
  442.